/* 
 * File:   OperacionSecuencial.cpp
 * Author: maximiliano
 * 
 * Created on 15 de junio de 2013, 17:20
 */

#include "client_OperacionSecuencial.h"
#include "common_MutexScopeLocker.h"

using namespace TP;
using namespace TP::Operaciones;

OperacionSecuencial::OperacionSecuencial(const uint32_t &pId) : Operacion(pId) {}

OperacionSecuencial::~OperacionSecuencial() {

    vector <Operacion*>::iterator it = _operaciones.begin();

    while (it < _operaciones.end())
    {
        delete (*it);
    }
    _operaciones.clear();
}

Operacion* OperacionSecuencial::AgregarOperacion (Operacion* pOperacion){
    if (NULL != pOperacion)
    {
        _operaciones.push_back(pOperacion);
    }
    return pOperacion;
}

void OperacionSecuencial::ejecutar(){
    
    Operacion* operacion = this->PrimeraOperacion();
    
    while (NULL != operacion)
    {
        operacion->ejecutar();
        while (!operacion->finalizada()) continue;
        operacion = this->SiguienteOperacion(operacion);
    }

    this->setFinalizada(true);
}

void OperacionSecuencial::procesarRespuesta (vector<string> &pRespuesta){
    
    // Itero las operaciones buscando la operacion pripietaria de la respuesta
    // (en funcion del token).
    
    vector<Operacion*>::iterator it = _operaciones.begin();
    
    while (it < _operaciones.end())
    {
        if ((*it)->asociado(pRespuesta))
        {
            // La operacion actual es la propietaria segun el token.

            (*it)->procesarRespuesta(pRespuesta);
        }
        it++;
    }
}

bool OperacionSecuencial::asociado(vector<string> &pRespuesta){
    
    bool asociado = false;
    
    vector<Operacion*>::iterator it = _operaciones.begin();
    
    while (it < _operaciones.end() && !asociado)
    {
        asociado = (*it)->asociado(pRespuesta);
        it++;
    }
    
    return asociado;    
}       

bool OperacionSecuencial::finalizada(){
    
    bool finalizada = true;
    
    vector<Operacion*>::iterator it = _operaciones.begin();
    
    while (it < _operaciones.end() && finalizada)
    {
        finalizada =  finalizada && (*it)->finalizada();
        it++;
    }
    
    return finalizada;
}

void OperacionSecuencial::LimpiarOperaciones(){
    
    if (this->finalizada())
    {
        vector <Operacion*>::iterator it = _operaciones.begin();
        while (it < _operaciones.end())
        {
            delete (*it);
            it++;
        }
        _operaciones.clear();
    }
}

Operacion* OperacionSecuencial::PrimeraOperacion(){
    
    Operacion* operacion = NULL;
    
    if (_operaciones.size() > 0) 
    {
        operacion = _operaciones[0];
    }
    
    return operacion;
}

Operacion* OperacionSecuencial::SiguienteOperacion(Operacion* pOperacionActual){
    
    size_t i = 0;
    bool encontrado = false;
    while (i < _operaciones.size() && !encontrado)
    {
        if (_operaciones[i] == pOperacionActual)
        {
            encontrado = true;
        }
        else
        {
            i++;
        }
    }
    
    Operacion* operacion = NULL; 
        
    if (encontrado && ( (i + 1) < _operaciones.size() ) )
    {
        operacion = _operaciones[++i];
    }
        
    return operacion;
}